﻿using System;
using System.Threading.Tasks;

namespace Netbits.Common.Threading
{
	/// <summary>
	/// Simple Task-helper
	/// </summary>
	public static class TaskHelper
	{
		#region Public static functions

		/// <summary>
		/// Run task with specified delegate.
		/// </summary>
		/// <param name="Delegate_">The delegate that must execute</param>
		public static void Run( Action Delegate_ )
		{
			Task.Factory.StartNew( () =>
			{
				Delegate_();
			} );
		}

		/// <summary>
		/// Run task with specified delegate and parameters.
		/// </summary>
		/// <typeparam name="T">Type of parameter</typeparam>
		/// <param name="Delegate_">The delegate that must execute</param>
		/// <param name="P1_">The first parameter</param>
		public static void Run<T>( Action<T> Delegate_, T P1_ )
		{
			Task.Factory.StartNew( () =>
				{
					Delegate_( P1_ );
				} );
		}

		/// <summary>
		/// Run task with specified delegate and parameters.
		/// </summary>
		/// <typeparam name="T1">Type of the first parameter</typeparam>
		/// <typeparam name="T2">Type of the second parameter</typeparam>
		/// <param name="Delegate_">The delegate that must execute</param>
		/// <param name="P1_">The first parameter</param>
		/// <param name="P2_">The second parameter</param>
		public static void Run<T1, T2>( Action<T1, T2> Delegate_, T1 P1_, T2 P2_ )
		{
			Task.Factory.StartNew( () =>
				{
					Delegate_( P1_, P2_ );
				} );
		}

		/// <summary>
		/// Run task with specified delegate and parameters.
		/// </summary>
		/// <typeparam name="T1">Type of the first parameter</typeparam>
		/// <typeparam name="T2">Type of the second parameter</typeparam>
		/// <typeparam name="T3">Type of the third parameter</typeparam>
		/// <param name="Delegate_">The delegate that must execute</param>
		/// <param name="P1_">The first parameter</param>
		/// <param name="P2_">The second parameter</param>
		/// <param name="P3_">The third parameter</param>
		public static void Run<T1, T2, T3>( Action<T1, T2, T3> Delegate_, T1 P1_, T2 P2_, T3 P3_ )
		{
			Task.Factory.StartNew( () =>
			{
				Delegate_( P1_, P2_, P3_ );
			} );
		}

		/// <summary>
		/// Run task with specified delegate and parameters.
		/// </summary>
		/// <typeparam name="T1">Type of the first parameter</typeparam>
		/// <typeparam name="T2">Type of the second parameter</typeparam>
		/// <typeparam name="T3">Type of the third parameter</typeparam>
		/// <typeparam name="T4">Type of the fourth parameter</typeparam>
		/// <param name="Delegate_">The delegate that must execute</param>
		/// <param name="P1_">The first parameter</param>
		/// <param name="P2_">The second parameter</param>
		/// <param name="P3_">The third parameter</param>
		/// <param name="P4_">The fourth parameter</param>
		public static void Run<T1, T2, T3, T4>( Action<T1, T2, T3, T4> Delegate_, T1 P1_, T2 P2_, T3 P3_, T4 P4_ )
		{
			Task.Factory.StartNew( () =>
			{
				Delegate_( P1_, P2_, P3_, P4_ );
			} );
		}

		/// <summary>
		/// Run task with specified delegate and parameters.
		/// </summary>
		/// <typeparam name="T1">Type of the first parameter</typeparam>
		/// <typeparam name="T2">Type of the second parameter</typeparam>
		/// <typeparam name="T3">Type of the third parameter</typeparam>
		/// <typeparam name="T4">Type of the fourth parameter</typeparam>
		/// <typeparam name="T5">Type of the fifth parameter</typeparam>
		/// <param name="Delegate_">The delegate that must execute</param>
		/// <param name="P1_">The first parameter</param>
		/// <param name="P2_">The second parameter</param>
		/// <param name="P3_">The third parameter</param>
		/// <param name="P4_">The fourth parameter</param>
		/// <param name="P5_">The fifth parameter</param>
		public static void Run<T1, T2, T3, T4, T5>( Action<T1, T2, T3, T4, T5> Delegate_, T1 P1_, T2 P2_, T3 P3_, T4 P4_, T5 P5_ )
		{
			Task.Factory.StartNew( () =>
			{
				Delegate_( P1_, P2_, P3_, P4_, P5_ );
			} );
		}

		/// <summary>
		/// Run task with specified delegate and parameters.
		/// </summary>
		/// <typeparam name="T1">Type of the first parameter</typeparam>
		/// <typeparam name="T2">Type of the second parameter</typeparam>
		/// <typeparam name="T3">Type of the third parameter</typeparam>
		/// <typeparam name="T4">Type of the fourth parameter</typeparam>
		/// <typeparam name="T5">Type of the fifth parameter</typeparam>
		/// <typeparam name="T6">Type of the sixth parameter</typeparam>
		/// <param name="Delegate_">The delegate that must execute</param>
		/// <param name="P1_">The first parameter</param>
		/// <param name="P2_">The second parameter</param>
		/// <param name="P3_">The third parameter</param>
		/// <param name="P4_">The fourth parameter</param>
		/// <param name="P5_">The fifth parameter</param>
		/// <param name="P6_">The sixth parameter</param>
		public static void Run<T1, T2, T3, T4, T5, T6>( Action<T1, T2, T3, T4, T5, T6> Delegate_, T1 P1_, T2 P2_, T3 P3_, T4 P4_, T5 P5_, T6 P6_ )
		{
			Task.Factory.StartNew( () =>
			{
				Delegate_( P1_, P2_, P3_, P4_, P5_, P6_ );
			} );
		}

		/// <summary>
		/// Run task with specified delegate and parameters.
		/// </summary>
		/// <typeparam name="T1">Type of the first parameter</typeparam>
		/// <typeparam name="T2">Type of the second parameter</typeparam>
		/// <typeparam name="T3">Type of the third parameter</typeparam>
		/// <typeparam name="T4">Type of the fourth parameter</typeparam>
		/// <typeparam name="T5">Type of the fifth parameter</typeparam>
		/// <typeparam name="T6">Type of the sixth parameter</typeparam>
		/// <typeparam name="T7">Type of the seventh parameter</typeparam>
		/// <param name="Delegate_">The delegate that must execute</param>
		/// <param name="P1_">The first parameter</param>
		/// <param name="P2_">The second parameter</param>
		/// <param name="P3_">The third parameter</param>
		/// <param name="P4_">The fourth parameter</param>
		/// <param name="P5_">The fifth parameter</param>
		/// <param name="P6_">The sixth parameter</param>
		/// <param name="P7_">The seventh parameter</param>
		public static void Run<T1, T2, T3, T4, T5, T6, T7>( Action<T1, T2, T3, T4, T5, T6, T7> Delegate_, T1 P1_, T2 P2_, T3 P3_, T4 P4_, T5 P5_, T6 P6_, T7 P7_ )
		{
			Task.Factory.StartNew( () =>
			{
				Delegate_( P1_, P2_, P3_, P4_, P5_, P6_, P7_ );
			} );
		}

		/// <summary>
		/// Run task with specified delegate and parameters.
		/// </summary>
		/// <typeparam name="T1">Type of the first parameter</typeparam>
		/// <typeparam name="T2">Type of the second parameter</typeparam>
		/// <typeparam name="T3">Type of the third parameter</typeparam>
		/// <typeparam name="T4">Type of the fourth parameter</typeparam>
		/// <typeparam name="T5">Type of the fifth parameter</typeparam>
		/// <typeparam name="T6">Type of the sixth parameter</typeparam>
		/// <typeparam name="T7">Type of the seventh parameter</typeparam>
		/// <typeparam name="T8">Type of the eighth parameter</typeparam>
		/// <param name="Delegate_">The delegate that must execute</param>
		/// <param name="P1_">The first parameter</param>
		/// <param name="P2_">The second parameter</param>
		/// <param name="P3_">The third parameter</param>
		/// <param name="P4_">The fourth parameter</param>
		/// <param name="P5_">The fifth parameter</param>
		/// <param name="P6_">The sixth parameter</param>
		/// <param name="P7_">The seventh parameter</param>
		/// <param name="P8_">The eighth parameter</param>
		public static void Run<T1, T2, T3, T4, T5, T6, T7, T8>( Action<T1, T2, T3, T4, T5, T6, T7, T8> Delegate_, T1 P1_, T2 P2_, T3 P3_, T4 P4_, T5 P5_, T6 P6_, T7 P7_, T8 P8_ )
		{
			Task.Factory.StartNew( () =>
			{
				Delegate_( P1_, P2_, P3_, P4_, P5_, P6_, P7_, P8_ );
			} );
		}

		/// <summary>
		/// Run task with specified delegate and parameters.
		/// </summary>
		/// <typeparam name="T1">Type of the first parameter</typeparam>
		/// <typeparam name="T2">Type of the second parameter</typeparam>
		/// <typeparam name="T3">Type of the third parameter</typeparam>
		/// <typeparam name="T4">Type of the fourth parameter</typeparam>
		/// <typeparam name="T5">Type of the fifth parameter</typeparam>
		/// <typeparam name="T6">Type of the sixth parameter</typeparam>
		/// <typeparam name="T7">Type of the seventh parameter</typeparam>
		/// <typeparam name="T8">Type of the eighth parameter</typeparam>
		/// <typeparam name="T9">Type of the ninth parameter</typeparam>
		/// <param name="Delegate_">The delegate that must execute</param>
		/// <param name="P1_">The first parameter</param>
		/// <param name="P2_">The second parameter</param>
		/// <param name="P3_">The third parameter</param>
		/// <param name="P4_">The fourth parameter</param>
		/// <param name="P5_">The fifth parameter</param>
		/// <param name="P6_">The sixth parameter</param>
		/// <param name="P7_">The seventh parameter</param>
		/// <param name="P8_">The eighth parameter</param>
		/// <param name="P9_">The ninth parameter</param>
		public static void Run<T1, T2, T3, T4, T5, T6, T7, T8, T9>( Action<T1, T2, T3, T4, T5, T6, T7, T8, T9> Delegate_, T1 P1_, T2 P2_, T3 P3_, T4 P4_, T5 P5_, T6 P6_, T7 P7_, T8 P8_, T9 P9_ )
		{
			Task.Factory.StartNew( () =>
			{
				Delegate_( P1_, P2_, P3_, P4_, P5_, P6_, P7_, P8_, P9_ );
			} );
		}

		/// <summary>
		/// Run task with specified function delegate
		/// </summary>
		/// <typeparam name="TResult">The result type</typeparam>
		/// <param name="Delegate_">The delegate that must execute</param>
		/// <returns>The result after the execution is finished</returns>
		public static TResult Run<TResult>( Func<TResult> Delegate_ )
		{
			return Task.Factory.StartNew( () =>
			{
				return Delegate_();
			} ).Result;
		}

		/// <summary>
		/// Run task with specified function delegate and parameters.
		/// </summary>
		/// <typeparam name="TResult">The result type</typeparam>
		/// <typeparam name="T">Type of the parameter</typeparam>
		/// <param name="Delegate_">The delegate that must execute</param>
		/// <param name="P_">The first parameter</param>
		/// <returns>The result after the execution is finished</returns>
		public static TResult Run<T, TResult>( Func<T, TResult> Delegate_, T P_ )
		{
			return Task.Factory.StartNew( () =>
				{
					return Delegate_( P_ );
				} ).Result;
		}

		/// <summary>
		/// Run task with specified function delegate and parameters.
		/// </summary>
		/// <typeparam name="TResult">The result type</typeparam>
		/// <typeparam name="T1">Type of the first parameter</typeparam>
		/// <typeparam name="T2">Type of the second parameter</typeparam>
		/// <param name="Delegate_">The delegate that must execute</param>
		/// <param name="P1_">The first parameter</param>
		/// <param name="P2_">The second parameter</param>
		/// <returns>The result after the execution is finished</returns>
		public static TResult Run<T1, T2, TResult>( Func<T1, T2, TResult> Delegate_, T1 P1_, T2 P2_ )
		{
			return Task.Factory.StartNew( () =>
			{
				return Delegate_( P1_, P2_ );
			} ).Result;
		}

		/// <summary>
		/// Run task with specified function delegate and parameters.
		/// </summary>
		/// <typeparam name="TResult">The result type</typeparam>
		/// <typeparam name="T1">Type of the first parameter</typeparam>
		/// <typeparam name="T2">Type of the second parameter</typeparam>
		/// <typeparam name="T3">Type of the third parameter</typeparam>
		/// <param name="Delegate_">The delegate that must execute</param>
		/// <param name="P1_">The first parameter</param>
		/// <param name="P2_">The second parameter</param>
		/// <param name="P3_">The third parameter</param>
		/// <returns>The result after the execution is finished</returns>
		public static TResult Run<T1, T2, T3, TResult>( Func<T1, T2, T3, TResult> Delegate_, T1 P1_, T2 P2_, T3 P3_ )
		{
			return Task.Factory.StartNew( () =>
			{
				return Delegate_( P1_, P2_, P3_ );
			} ).Result;
		}

		/// <summary>
		/// Run task with specified function delegate and parameters.
		/// </summary>
		/// <typeparam name="TResult">The result type</typeparam>
		/// <typeparam name="T1">Type of the first parameter</typeparam>
		/// <typeparam name="T2">Type of the second parameter</typeparam>
		/// <typeparam name="T3">Type of the third parameter</typeparam>
		/// <typeparam name="T4">Type of the fourth parameter</typeparam>
		/// <param name="Delegate_">The delegate that must execute</param>
		/// <param name="P1_">The first parameter</param>
		/// <param name="P2_">The second parameter</param>
		/// <param name="P3_">The third parameter</param>
		/// <param name="P4_">The fourth parameter</param>
		/// <returns>The result after the execution is finished</returns>
		public static TResult Run<T1, T2, T3, T4, TResult>( Func<T1, T2, T3, T4, TResult> Delegate_, T1 P1_, T2 P2_, T3 P3_, T4 P4_ )
		{
			return Task.Factory.StartNew( () =>
			{
				return Delegate_( P1_, P2_, P3_, P4_ );
			} ).Result;
		}

		/// <summary>
		/// Run task with specified function delegate and parameters.
		/// </summary>
		/// <typeparam name="TResult">The result type</typeparam>
		/// <typeparam name="T1">Type of the first parameter</typeparam>
		/// <typeparam name="T2">Type of the second parameter</typeparam>
		/// <typeparam name="T3">Type of the third parameter</typeparam>
		/// <typeparam name="T4">Type of the fourth parameter</typeparam>
		/// <typeparam name="T5">Type of the fifth parameter</typeparam>
		/// <param name="Delegate_">The delegate that must execute</param>
		/// <param name="P1_">The first parameter</param>
		/// <param name="P2_">The second parameter</param>
		/// <param name="P3_">The third parameter</param>
		/// <param name="P4_">The fourth parameter</param>
		/// <param name="P5_">The fifth parameter</param>
		/// <returns>The result after the execution is finished</returns>
		public static TResult Run<T1, T2, T3, T4, T5, TResult>( Func<T1, T2, T3, T4, T5, TResult> Delegate_, T1 P1_, T2 P2_, T3 P3_, T4 P4_, T5 P5_ )
		{
			return Task.Factory.StartNew( () =>
			{
				return Delegate_( P1_, P2_, P3_, P4_, P5_ );
			} ).Result;
		}

		/// <summary>
		/// Run task with specified function delegate and parameters.
		/// </summary>
		/// <typeparam name="TResult">The result type</typeparam>
		/// <typeparam name="T1">Type of the first parameter</typeparam>
		/// <typeparam name="T2">Type of the second parameter</typeparam>
		/// <typeparam name="T3">Type of the third parameter</typeparam>
		/// <typeparam name="T4">Type of the fourth parameter</typeparam>
		/// <typeparam name="T5">Type of the fifth parameter</typeparam>
		/// <typeparam name="T6">Type of the sixth parameter</typeparam>
		/// <param name="Delegate_">The delegate that must execute</param>
		/// <param name="P1_">The first parameter</param>
		/// <param name="P2_">The second parameter</param>
		/// <param name="P3_">The third parameter</param>
		/// <param name="P4_">The fourth parameter</param>
		/// <param name="P5_">The fifth parameter</param>
		/// <param name="P6_">The sixth parameter</param>
		/// <returns>The result after the execution is finished</returns>
		public static TResult Run<T1, T2, T3, T4, T5, T6, TResult>( Func<T1, T2, T3, T4, T5, T6, TResult> Delegate_, T1 P1_, T2 P2_, T3 P3_, T4 P4_, T5 P5_, T6 P6_ )
		{
			return Task.Factory.StartNew( () =>
			{
				return Delegate_( P1_, P2_, P3_, P4_, P5_, P6_ );
			} ).Result;
		}

		/// <summary>
		/// Run task with specified function delegate and parameters.
		/// </summary>
		/// <typeparam name="TResult">The result type</typeparam>
		/// <typeparam name="T1">Type of the first parameter</typeparam>
		/// <typeparam name="T2">Type of the second parameter</typeparam>
		/// <typeparam name="T3">Type of the third parameter</typeparam>
		/// <typeparam name="T4">Type of the fourth parameter</typeparam>
		/// <typeparam name="T5">Type of the fifth parameter</typeparam>
		/// <typeparam name="T6">Type of the sixth parameter</typeparam>
		/// <typeparam name="T7">Type of the seventh parameter</typeparam>
		/// <param name="Delegate_">The delegate that must execute</param>
		/// <param name="P1_">The first parameter</param>
		/// <param name="P2_">The second parameter</param>
		/// <param name="P3_">The third parameter</param>
		/// <param name="P4_">The fourth parameter</param>
		/// <param name="P5_">The fifth parameter</param>
		/// <param name="P6_">The sixth parameter</param>
		/// <param name="P7_">The seventh parameter</param>
		/// <returns>The result after the execution is finished</returns>
		public static TResult Run<T1, T2, T3, T4, T5, T6, T7, TResult>( Func<T1, T2, T3, T4, T5, T6, T7, TResult> Delegate_, T1 P1_, T2 P2_, T3 P3_, T4 P4_, T5 P5_, T6 P6_, T7 P7_ )
		{
			return Task.Factory.StartNew( () =>
			{
				return Delegate_( P1_, P2_, P3_, P4_, P5_, P6_, P7_ );
			} ).Result;
		}

		/// <summary>
		/// Run task with specified function delegate and parameters.
		/// </summary>
		/// <typeparam name="TResult">The result type</typeparam>
		/// <typeparam name="T1">Type of the first parameter</typeparam>
		/// <typeparam name="T2">Type of the second parameter</typeparam>
		/// <typeparam name="T3">Type of the third parameter</typeparam>
		/// <typeparam name="T4">Type of the fourth parameter</typeparam>
		/// <typeparam name="T5">Type of the fifth parameter</typeparam>
		/// <typeparam name="T6">Type of the sixth parameter</typeparam>
		/// <typeparam name="T7">Type of the seventh parameter</typeparam>
		/// <typeparam name="T8">Type of the eighth parameter</typeparam>
		/// <param name="Delegate_">The delegate that must execute</param>
		/// <param name="P1_">The first parameter</param>
		/// <param name="P2_">The second parameter</param>
		/// <param name="P3_">The third parameter</param>
		/// <param name="P4_">The fourth parameter</param>
		/// <param name="P5_">The fifth parameter</param>
		/// <param name="P6_">The sixth parameter</param>
		/// <param name="P7_">The seventh parameter</param>
		/// <param name="P8_">The eighth parameter</param>
		/// <returns>The result after the execution is finished</returns>
		public static TResult Run<T1, T2, T3, T4, T5, T6, T7, T8, TResult>( Func<T1, T2, T3, T4, T5, T6, T7, T8, TResult> Delegate_, T1 P1_, T2 P2_, T3 P3_, T4 P4_, T5 P5_, T6 P6_, T7 P7_, T8 P8_ )
		{
			return Task.Factory.StartNew( () =>
			{
				return Delegate_( P1_, P2_, P3_, P4_, P5_, P6_, P7_, P8_ );
			} ).Result;
		}

		/// <summary>
		/// Run task with specified function delegate and parameters.
		/// </summary>
		/// <typeparam name="TResult">The result type</typeparam>
		/// <typeparam name="T1">Type of the first parameter</typeparam>
		/// <typeparam name="T2">Type of the second parameter</typeparam>
		/// <typeparam name="T3">Type of the third parameter</typeparam>
		/// <typeparam name="T4">Type of the fourth parameter</typeparam>
		/// <typeparam name="T5">Type of the fifth parameter</typeparam>
		/// <typeparam name="T6">Type of the sixth parameter</typeparam>
		/// <typeparam name="T7">Type of the seventh parameter</typeparam>
		/// <typeparam name="T8">Type of the eighth parameter</typeparam>
		/// <typeparam name="T9">Type of the ninth parameter</typeparam>
		/// <param name="Delegate_">The delegate that must execute</param>
		/// <param name="P1_">The first parameter</param>
		/// <param name="P2_">The second parameter</param>
		/// <param name="P3_">The third parameter</param>
		/// <param name="P4_">The fourth parameter</param>
		/// <param name="P5_">The fifth parameter</param>
		/// <param name="P6_">The sixth parameter</param>
		/// <param name="P7_">The seventh parameter</param>
		/// <param name="P8_">The eighth parameter</param>
		/// <param name="P9_">The ninth parameter</param>
		/// <returns>The result after the execution is finished</returns>
		public static TResult Run<T1, T2, T3, T4, T5, T6, T7, T8, T9, TResult>( Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, TResult> Delegate_, T1 P1_, T2 P2_, T3 P3_, T4 P4_, T5 P5_, T6 P6_, T7 P7_, T8 P8_, T9 P9_ )
		{
			return Task.Factory.StartNew( () =>
			{
				return Delegate_( P1_, P2_, P3_, P4_, P5_, P6_, P7_, P8_, P9_ );
			} ).Result;
		}

		#endregion
	}
}
